<template>
  <div class="dict-form-wrapper">
    <div class="form-title">{{ isEdit ? titleEdit : titleAdd }}</div>
    <div v-loading="loading" element-loading-text="加载中..." class="form-content">
      <el-form ref="form" :model="form" :rules="rules" label-width="80px" size="small" class="dict-form">
      <el-form-item label="编码" prop="code">
        <el-input :id="`code-${uid}`" name="code" v-model="form.code" placeholder="请输入" />
      </el-form-item>
      <el-form-item :label="nameLabel" prop="name">
        <el-input :id="`name-${uid}`" name="name" v-model="form.name" :placeholder="`请输入${nameLabel}`" />
      </el-form-item>
      <el-form-item v-if="showColor" label="颜色" prop="colorHex">
        <div class="switch-with-text" @click="showColorPicker = true">
          <div :style="{width:'20px',height:'20px',backgroundColor: form.colorHex || '#409EFF',border:'1px solid #dcdfe6',borderRadius:'4px',cursor:'pointer'}"></div>
          <span class="color-text">点击选择颜色</span>
        </div>
      </el-form-item>
      <!-- 扩展位：业务可通过具名插槽传入额外表单项（显示在是否启用之前） -->
      <slot name="extra" :form="form"></slot>
      <el-form-item label="是否启用" prop="enabled">
        <div class="switch-with-text">
          <el-switch :id="`enabled-${uid}`" name="enabled" v-model="form.enabled" :active-value="1" :inactive-value="0" :disabled="disableEnabled" />
          <span class="switch-text" :style="{ color: disableEnabled ? '#c0c4cc' : '#303133' }">{{ form.enabled===1 ? '启用' : '禁用' }}</span>
        </div>
      </el-form-item>
      <div class="footer">
        <el-button type="primary" size="small" @click="confirmAndBack">确认</el-button>
        <el-button size="small" @click="goBack">取消</el-button>
      </div>
      </el-form>
    </div>

    <el-dialog title="选择颜色" :visible.sync="showColorPicker" width="400px" append-to-body>
      <el-color-picker :id="`color-${uid}`" name="colorHex" v-model="form.colorHex" :show-alpha="true" color-format="rgba"></el-color-picker>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="showColorPicker = false">确定</el-button>
        <el-button @click="showColorPicker = false">取消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: 'DictBasicForm',
  components: { },
  props: {
    mode: { type: String, default: 'create' },
    code: { type: String, default: '' },
    titleAdd: { type: String, required: true },
    titleEdit: { type: String, required: true },
    nameLabel: { type: String, default: '名称' },
    showColor: { type: Boolean, default: false },
    api: { // { get, add, update }
      type: Object,
      required: true
    },
    // 额外初始字段（例如 { category: null }）
    extendInit: {
      type: Object,
      default: () => ({})
    },
    // 额外校验规则（会与基础规则 merge）
    extraRules: {
      type: Object,
      default: () => ({})
    },
    // 是否禁用“是否启用”开关（用于使用中不允许更改）
    disableEnabled: { type: Boolean, default: false }
  },
  data() {
    return {
      uid: Date.now().toString(36),
      showColorPicker: false,
      loading: false,
      form: {
        code: null,
        name: null,
        colorHex: '#409EFF',
        enabled: 1
      },
      originalSnapshot: null,
      originalCode: null,
      rules: {
        code: [
          { required: true, message: '编码不能为空', trigger: 'blur' },
          { pattern: /^[^.]*$/, message: '编码不能包含小数点', trigger: 'blur' }
        ],
        name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
        enabled: [{ required: true, message: '是否启用不能为空', trigger: 'change' }]
      }
    }
  },
  computed: {
    isEdit() { return this.mode === 'edit' && this.code }
  },
  async created() {
    // 合并扩展初始字段
    this.form = Object.assign({}, this.form, this.extendInit)
    // 合并额外规则
    this.rules = Object.assign({}, this.rules, this.extraRules)
    if (this.isEdit) {
      this.loading = true
      try {
        const res = await this.api.get(this.code)
        // 标准化 enabled 类型为数字，避免与开关 active/inactive 值(1/0) 严格比较不相等
        const data = { ...res.data }
        if (data) {
          const v = data.enabled
          // 缺省默认启用；布尔/字符串/数字统一成 1/0
          data.enabled = (v === undefined || v === null)
            ? 1
            : ((v === 1 || v === '1' || v === true) ? 1 : 0)
        }
        this.form = data
        this.originalCode = data.code
        // 记录原始快照用于"无改动不提交"
        const baseKeys = ['code', 'name', 'enabled']
        const extraKeys = Object.keys(this.extendInit || {})
        const allowed = new Set([...baseKeys, ...extraKeys, this.showColor ? 'colorHex' : ''])
        const snap = {}
        Object.keys(this.form || {}).forEach(k => { if (allowed.has(k) && this.form[k] !== undefined) snap[k] = this.form[k] })
        this.originalSnapshot = snap
      } catch (error) {
        console.error('加载数据失败:', error)
        this.$modal.msgError('加载数据失败，请重试')
      } finally {
        this.loading = false
      }
    }
  },
  methods: {
    confirmAndBack() {
      const action = this.isEdit ? this.api.update : this.api.add
      this.$refs.form.validate(valid => {
        if (!valid) return
        // 精简提交字段，避免后端因多余字段或不可修改字段失败
        const baseKeys = ['code', 'name', 'enabled']
        const extraKeys = Object.keys(this.extendInit || {})
        const allowedKeys = new Set([...baseKeys, ...extraKeys, this.showColor ? 'colorHex' : ''])
        const payload = {}
        Object.keys(this.form || {}).forEach(k => { if (allowedKeys.has(k) && this.form[k] !== undefined) payload[k] = this.form[k] })
        // 若允许修改编码，且编辑态下编码发生变化，则携带 oldCode
        if (this.isEdit && this.originalCode && this.form.code && this.form.code !== this.originalCode) {
          payload.oldCode = this.originalCode
        }
        // 若编辑模式且无任何改动，则不调用后端，直接提示
        if (this.isEdit && this.originalSnapshot) {
          const snap = this.originalSnapshot
          const changed = Object.keys(payload).some(k => payload[k] !== snap[k])
          if (!changed) {
            this.$modal.msgSuccess({ message: '无变更', duration: 600 })
            this.goBack()
            return
          }
        }
        action(payload).then(() => {
          this.$modal.msgSuccess({ message: '保存成功', duration: 800 })
          // 在弹窗场景：通知父组件刷新并关闭
          this.$emit('success')
        })
      })
    },
    goBack() {
      // 检查表单是否有更改
      if (this.isEdit && this.originalSnapshot) {
        const baseKeys = ['code', 'name', 'enabled']
        const extraKeys = Object.keys(this.extendInit || {})
        const allowedKeys = new Set([...baseKeys, ...extraKeys, this.showColor ? 'colorHex' : ''])
        const currentData = {}
        Object.keys(this.form || {}).forEach(k => {
          if (allowedKeys.has(k) && this.form[k] !== undefined) currentData[k] = this.form[k]
        })

        const changed = Object.keys(currentData).some(k => currentData[k] !== this.originalSnapshot[k])
        if (changed) {
          this.$modal.confirm('内容没有保存，是否取消？').then(() => {
            // 在弹窗场景：仅通知父组件关闭
            this.$emit('close')
          }).catch(() => {
            // 用户点击取消，不执行任何操作
          })
          return
        }
      }
      // 在弹窗场景：仅通知父组件关闭
      this.$emit('close')
    }
  }
}
</script>

<style scoped>
.dict-form-wrapper {
  max-width: 520px;
  margin: 24px auto;
  background: #fff;
  padding: 16px 20px;
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
}
.form-title { font-size: 16px; font-weight: 600; color: #303133; margin-bottom: 12px; }
.form-content { min-height: 200px; }
.switch-with-text { display: inline-flex; align-items: center; }
.switch-text { margin-left: 8px; color: #303133; }
.color-text { margin-left: 8px; color: #909399; cursor: pointer; }
.footer { text-align: right; margin-top: 8px; }
</style>


